package com.sdp.wx.onlyoffice;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.sdp.core.bizc.db.Query;
import com.sdp.core.bizc.vo.DataCenter;
import com.sdp.core.bizc.vo.Result;
import com.sdp.wx.db.on_file.entity.OnFile;
import com.sdp.wx.db.on_file.service.IOnFileService;
import com.sdp.wx.utils.LocalDateUtil;
import org.apache.commons.io.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.Scanner;

@RestController
@RequestMapping("/onlyofficeController")
public class onlyofficeController {

    @Autowired
    private IOnFileService iOnFileService;
    @Autowired
    private Query query;

    @Value("${sdp.filePath}")
    private String filePath;

    /**
     * 所有系统上传的文件都存在此文件夹下
     */
    private String onlyofficeFiles = "onlyofficeFiles";

    @PostMapping(value = "/page")
    public Result<?> page(@RequestBody DataCenter dataCenter) {
        return Result.ok(query.page(iOnFileService, OnFile.class, dataCenter));
    }

    /**
     * 新建文档信息
     * @param onFile
     * @return
     */
    @RequestMapping("/save")
    public Result<?> save(@RequestBody OnFile onFile) throws IOException {
        if(StringUtils.isEmpty(onFile.getFileName())){
            return Result.error("文件名称不能为空");
        }
        if(StringUtils.isEmpty(onFile.getFileType())){
            return Result.error("文件类型不能为空");
        }
        String getLocalDate=LocalDateUtil.getLocalDate();
        String dbpath=onlyofficeFiles+"/"+getLocalDate+"."+onFile.getFileType();
        String filePath =this.filePath+"/"+onlyofficeFiles;
        // 创建文件
        File target = new File(filePath);
        if (!target.exists()) {
            target.mkdirs();
        }
        String office =filePath+"/"+getLocalDate+"."+onFile.getFileType();
        if(onFile.getFileType().equals("pdf")){
            PdfWriter writer =  new PdfWriter(office);
            PdfDocument pdfDocument = new PdfDocument(writer);
            pdfDocument.close();
        }else{
            File file = new File(office);
            file.createNewFile();
        }
        onFile.setFileSite(dbpath);
        onFile.setFileId(getLocalDate);
        onFile.setVersion(getLocalDate);
        onFile.setCreateTime(LocalDateTime.now());
        iOnFileService.save(onFile);
        return Result.ok(onFile);
    }

    /**
     * 文档编辑服务使用JavaScript API通知callbackUrl，向文档存储服务通知文档编辑的状态。
     * 文档编辑服务使用具有正文中的信息的POST请求。
     * https://api.onlyoffice.com/editors/callback
     * <p>
     * 当我们关闭编辑窗口后，十秒钟左右only office会将它存储的我们的编辑后的文件
     * 0 - 找不到具有密钥标识符的文档
     * 1 - 正在编辑文档
     * 2 - 文档已准备好保存
     * 3 - 发生文档保存错误
     * 4 - 不作任何更改就关闭文档
     * 6 - 正在编辑文档，但保存当前文档状态
     * 7 - 强制保存文档时发生错误
     *
     */
    @ResponseBody
    @PostMapping(value = "/callbackSave")
    public void callbackSave(HttpServletRequest request, HttpServletResponse response) throws IOException {
        PrintWriter writer = response.getWriter();
        String body = "";
        try {
            Scanner scanner = new Scanner(request.getInputStream());
            scanner.useDelimiter("\\A");
            body = scanner.hasNext() ? scanner.next() : "";
            scanner.close();
        } catch (Exception ex) {
            writer.write("get request.getInputStream error:" + ex.getMessage());
            return;
        }
        if (body.isEmpty()) {
            writer.write("empty request.getInputStream");
            return;
        }
        JSONObject jsonObj = JSON.parseObject(body);
        System.out.println("回调参数对象 =====》》》 " + jsonObj);
        int status = (Integer) jsonObj.get("status");
        int saved = 0;
        //status=6,表示点击保存按钮
        if (status == 6) //MustSave, Corrupted
        {
            InputStream stream=null;
            OutputStream outputStream=null;
            try {
            QueryWrapper<OnFile> queryWrapper=new QueryWrapper<>();
            queryWrapper.lambda().eq(OnFile::getKeyId,jsonObj.get("key").toString().split(",")[0]);
            OnFile onFile= iOnFileService.getOne(queryWrapper,false);
            if(onFile == null){
                throw new Exception("文件不存在");
            }
           //获取url
            String downloadUri = (String) jsonObj.get("url");
            //获取onlyOffice缓存中的文件流
            URL url = new URL(downloadUri);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
             stream = connection.getInputStream();
            if (stream == null) {
                throw new Exception("Stream is null");
            }
            String getLocalDate=LocalDateUtil.getLocalDate();
            //上传新文件到文件服务器
            String oidfilePath=this.filePath+File.separator+onFile.getFileSite();
            // 删除旧文件
             File file = new File(oidfilePath);
             if (file.exists()) {
                file.delete();
             }
                String filePath=onlyofficeFiles+File.separator+getLocalDate+"."+onFile.getFileType();
                String newfilePath= this.filePath+File.separator+filePath;
                File newfile = new File(newfilePath);
                outputStream = new FileOutputStream(newfile);
                //这里也很关键每次读取的大小为5M 不一次性读取完
                byte[] buffer = new byte[1024 * 1024 * 5];// 5MB
                int len = 0;
                while ((len = stream.read(buffer)) != -1) {
                    outputStream.write(buffer, 0, len);
                }
                connection.disconnect();
                onFile.setFileSite(filePath);
                onFile.setVersion(getLocalDate);
                iOnFileService.updateById(onFile);
            } catch (Exception ex) {
                saved = 3;
                ex.printStackTrace();
            }finally {
                IOUtils.closeQuietly(outputStream);
                IOUtils.closeQuietly(stream);
            }
        }
        writer.write("{\"error\":" + saved + "}");
    }
}
